using System;
using System.Collections;
using System.Collections.Generic;
using FluentTests.Framework.VerbExtensions;
using FluentTests.Framework.Verbs;
using System.Linq;

namespace FluentTests.Framework
{
    public interface IEnsuredWrapper
    {
        IAssertionProvider AssertionProvider { get; }
    }

    public class EnsuredWrapper<T> : IEnsuredWrapper
    {
        protected readonly IAssertionProvider assertionProvider;
        protected readonly T actualValue;

        public EnsuredWrapper(IAssertionProvider assertionProvider,T actualValue)
        {
            this.assertionProvider = assertionProvider;
            this.actualValue = actualValue;
        }

        public Is<T> Is
        {
            get
            {
                return new Is<T>(this);
            }
        }

        

        public Are<T> Are
        {
            get
            {
                return new Are<T>(this);
            }
        }

        public Has<T> Has
        {
            get
            {
                return new Has<T>(this);
            }
        }

        public override bool Equals(object obj)
        {
            new EnsuredWrapper<object>(this.assertionProvider,this.actualValue).Is.EqualTo(obj);
            return true;
        }

        public IAssertionProvider AssertionProvider { get { return assertionProvider; } }

        public T ActualValue { get { return actualValue; } }
    }

    public interface ICollectionEnsuredWrapper<out T, out TElementType> : IEnsuredWrapper where T : IEnumerable<TElementType>
    {
        ICollectionEnsuredWrapper<T, TElementType> Where(Func<TElementType, bool> predicate);
    }

    public class CollectionEnsuredWrapper<T, TElementType> : EnsuredWrapper<T> where T : IEnumerable<TElementType>
    {
        public CollectionEnsuredWrapper(IAssertionProvider assertionProvider, T actualValue) : base(assertionProvider, actualValue)
        {

        }

        public CollectionEnsuredWrapper<T,TElementType> Where(Func<TElementType,bool> predicate) 
        {
            var newValue = (T) this.actualValue.Where(predicate);
            return new CollectionEnsuredWrapper<T,TElementType>(assertionProvider, newValue);
        }

        public new GenericHas<T,TElementType> Has
        {
            get
            {
                return new GenericHas<T,TElementType>(this);
            }
        }

    }


}